package com.tuoku.onepass.view

import android.content.Context
import android.graphics.Canvas
import android.graphics.Color
import android.graphics.Paint
import android.graphics.PointF
import android.util.AttributeSet
import android.view.MotionEvent
import android.view.View
import androidx.core.content.withStyledAttributes
import com.tuoku.onepass.R

class GestureLockView @JvmOverloads constructor(
    context: Context,
    attrs: AttributeSet? = null,
    defStyleAttr: Int = 0
) : View(context, attrs, defStyleAttr) {

    private var normalColor = Color.GRAY
    private var selectedColor = Color.BLUE
    private var errorColor = Color.RED
    private var circleRadius = 60f
    private var circleStrokeWidth = 5f
    private var lineStrokeWidth = 15f

    private var drawingWidth = 0
    private var drawingHeight = 0

    private val pointList = mutableListOf<PointF>()
    private val selectedPoints = mutableListOf<Int>()
    private var currentX = 0f
    private var currentY = 0f

    private var listener: OnGestureLockListener? = null

    init {
        initAttrs(attrs)
        viewTreeObserver.addOnGlobalLayoutListener {
            drawingWidth = width
            drawingHeight = height
            var x0 = drawingWidth * 0.15f
            var x1 = drawingWidth * 0.5f
            var x2 = drawingWidth * 0.85f
            var y0 = drawingHeight * 0.15f
            var y1 = drawingHeight * 0.5f
            var y2 = drawingHeight * 0.85f
            pointList.add(PointF(x0, y0))
            pointList.add(PointF(x1, y0))
            pointList.add(PointF(x2, y0))
            pointList.add(PointF(x0, y1))
            pointList.add(PointF(x1, y1))
            pointList.add(PointF(x2, y1))
            pointList.add(PointF(x0, y2))
            pointList.add(PointF(x1, y2))
            pointList.add(PointF(x2, y2))
            // 触发重绘
            invalidate()
        }
    }

    private fun initAttrs(attrs: AttributeSet?) {
        context.withStyledAttributes(attrs, R.styleable.GestureLockView) {
            normalColor = getColor(R.styleable.GestureLockView_normalColor, normalColor)
            selectedColor = getColor(R.styleable.GestureLockView_selectedColor, selectedColor)
            errorColor = getColor(R.styleable.GestureLockView_errorColor, errorColor)
            circleRadius = getDimension(R.styleable.GestureLockView_circleRadius, circleRadius)
            circleStrokeWidth = getDimension(R.styleable.GestureLockView_circleStrokeWidth, circleStrokeWidth)
        }
    }

    override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec)
        val width = MeasureSpec.getSize(widthMeasureSpec)
        val height = MeasureSpec.getSize(heightMeasureSpec)
        setMeasuredDimension(width, height)
    }

    override fun onDraw(canvas: Canvas) {
        super.onDraw(canvas)
        drawCircles(canvas)
        drawLines(canvas)
    }

    private fun drawCircles(canvas: Canvas) {
        // 绘制9宫格圆点
        val paint = Paint(Paint.ANTI_ALIAS_FLAG).apply {
            color = normalColor
            style = Paint.Style.STROKE
            strokeWidth = circleStrokeWidth
        }
        val selectedPaint = Paint(Paint.ANTI_ALIAS_FLAG).apply {
            color = selectedColor
            style = Paint.Style.FILL
        }
        pointList.forEach { point ->
            canvas.drawCircle(point.x, point.y, circleRadius, paint)
        }
        selectedPoints.forEach { pointIndex ->
            val point = pointList[pointIndex]
            canvas.drawCircle(point.x, point.y, circleRadius / 2, selectedPaint)
        }
    }

    private fun drawLines(canvas: Canvas) {
        // 绘制连接线
        // 选择点少于两个不绘制线
        if (selectedPoints.size < 2) {
            return
        }
        val linePaint = Paint(Paint.ANTI_ALIAS_FLAG).apply {
            color = selectedColor
            strokeWidth = lineStrokeWidth
            style = Paint.Style.STROKE
        }
        for (i in 0 until selectedPoints.size - 1) {
            val startPoint = pointList[selectedPoints[i]]
            val endPoint = pointList[selectedPoints[i + 1]]
            canvas.drawLine(startPoint.x, startPoint.y, endPoint.x, endPoint.y, linePaint)
        }
    }

    override fun onTouchEvent(event: MotionEvent): Boolean {
        when (event.action) {
            MotionEvent.ACTION_DOWN -> {
                selectedPoints.clear()
                listener?.onStarted()
                // 处理手势开始逻辑
                currentX = event.x
                currentY = event.y
                // 判断起手点是否在某个预置点范围内，不在则提示，在的话加入选择点
                val pointIndex = getSelectedPoint(currentX, currentY)
                if (pointIndex == -1) {
                    listener?.onError("请移动到预设的点位")
                } else {
                    selectedPoints.add(pointIndex)
                    // 触发重绘
                    invalidate()
                }
            }
            MotionEvent.ACTION_MOVE -> {
                // 处理移动事件
                currentX = event.x
                currentY = event.y
                // 判断起手点是否在某个预置点范围内，在的话加入选择点
                val pointIndex = getSelectedPoint(currentX, currentY)
                if (pointIndex > -1) {
                    // 因为MOVE事件是一个连续事件，此处需要多判断一下选点列表末尾是否已经存在，不存在则加入
                    if (selectedPoints.isEmpty() || selectedPoints.last() != pointIndex) {
                        selectedPoints.add(pointIndex)
                        // 触发重绘
                        invalidate()
                    }
                }
            }
            MotionEvent.ACTION_UP -> {
                if (selectedPoints.size >= 4) {
                    // 生成密码并回调
                    listener?.onComplete(generatePassword())
                } else {
                    listener?.onError("请至少连接4个点")
                }
            }
        }
        return true
    }

    private fun getSelectedPoint(currentX: Float, currentY: Float): Int {
        for (i in 0 until pointList.size) {
            val point = pointList[i]
            val inCircle = isCurrentPointInCircle(currentX, currentY, point.x, point.y, circleRadius)
            if (inCircle) {
                return i
            }
        }
        return -1
    }

    private fun isCurrentPointInCircle(currentX: Float, currentY: Float, pointX: Float, pointY: Float, radius: Float): Boolean {
        val dx = currentX - pointX
        val dy = currentY - pointY
        return dx * dx + dy * dy <= radius * radius // 避免开方运算优化性能
    }

    private fun generatePassword(): String {
        // 实现密码生成逻辑
        val strBul = StringBuilder()
        for (item in selectedPoints) {
            strBul.append(item)
        }
        return strBul.toString()
    }

    fun reset() {
        selectedPoints.clear()
        invalidate()
    }

    // 添加监听器设置方法
    fun setOnGestureLockListener(listener: OnGestureLockListener) {
        this.listener = listener
    }

    interface OnGestureLockListener {
        fun onComplete(password: String)
        fun onStarted()
        fun onError(message: String)
    }
}